package com.ruoyi.im.websocket;

import com.ruoyi.im.domain.CcsChatMessage;
import com.ruoyi.im.service.ICcsChatMessageService;
import com.ruoyi.im.websocket.protocol.WebSocketCodec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Optional;

@Component
@Slf4j
public class HttpAuthHandler extends TextWebSocketHandler {

    @Autowired
    private ICcsChatMessageService ccsChatMessageService;

    /**
     * socket 建立成功事件
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Object sessionId = session.getAttributes().get("userId");
        log.info("用户连接成功: {}", sessionId);
        if (sessionId != null) {
            // 用户连接成功，放入在线用户缓存
            WsSessionManager.add(sessionId.toString(), session);
        } else {
            throw new RuntimeException("用户登录已经失效!");
        }
    }

    /**
     * 接收消息事件
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("收到消息: {}", message.getPayload());
        // 获得客户端传来的消息
        // 据格式为 sessionId:from:to:type:message
        // 1. 获取数据包
        String packet = message.getPayload();
        // 2. 解析数据包
        Optional<CcsChatMessage> msg = Optional.ofNullable(WebSocketCodec.decode(packet));
        log.info("消息实体: {}", msg);
        // 3. 消息合法，则进行存储
        msg.ifPresent(bean -> {
            boolean isSuccess = ccsChatMessageService.saveMessage(bean);
            // 消息存储成功后，如果 接收者 在线，则尝试发生消息
            if (isSuccess) {
                // 3.1 获取 接收者 会话，通过 to (userId)
                Optional<WebSocketSession> to = Optional.ofNullable(WsSessionManager.get(bean.getReceiveId().toString()));
                to.ifPresent(toSession -> {
                    // 3.2 发送消息给 接收者
                    try {
                        toSession.sendMessage(new TextMessage(WebSocketCodec.encode(bean)));
                    } catch (Exception e) {
                        log.error("消息发送失败", e);
                    }
                });
            }
        });
    }

    /**
     * socket 断开连接时
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Object sessionId = session.getAttributes().get("userId");
        log.info("用户断开连接: {}", sessionId);
        if (sessionId != null) {
            // 用户退出，移除缓存
            WsSessionManager.remove(sessionId.toString());
        }
    }


}
